import 'dart:convert';

import 'package:logger/logger.dart';
import 'package:sqflite/sqflite.dart';
import '../pojo/ImPojo.dart';
import '../socket/dto/business/PullData.dart';
import '../util/DateUtil.dart';
import '../util/ImSingleton.dart';
import '../util/MapUtil.dart';
import 'BaseDao.dart';

class ImGroupUserDao extends BaseDao {

  final _logger = Logger(
    printer: PrettyPrinter(),
  );

  Future<void> batchInserts(int groupId, Set<ImGroupUser> groupUsers) async {
    if (groupUsers.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var groupUser in groupUsers) {
      var data = _toInsertValueMap(groupId, groupUser);
      data['groupId'] = groupId;
      batch?.insert("im_group_user", data);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch json: " + jsonEncode(list));
  }

  Future<void> batchUpdates(Set<ImGroupUser> groupUsers) async {
    if (groupUsers.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var groupUser in groupUsers) {
      var data = _toUpdateValueMap(groupUser);
      batch?.update("im_group_user", data, where: "id = ?", whereArgs: [groupUser.id]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch json: " + jsonEncode(list));
  }

  Future<void> insertOrUpdates(List<ImGroupUser> groupUsers) async {
    if (groupUsers.isEmpty) return;
    List<ImGroupUser> insertGroupUsers = [];
    List<ImGroupUser> updateGroupUsers = [];
    var groupId = null;
    for (var groupUser in groupUsers) {
      groupId = groupUser.groupId!;
      var dbGroupUser = await getByGroupIdAndUserId(groupUser.groupId!, groupUser.userId);
      if (dbGroupUser != null) {
        updateGroupUsers.add(groupUser);
      } else {
        insertGroupUsers.add(groupUser);
      }
    }
    batchInserts(groupId, insertGroupUsers.toSet());
    batchUpdates(updateGroupUsers.toSet());
  }

  Future<List<ImGroupUser>> getByGroupId(int groupId) async {
    Database? database = getDatabase(); //await getReadOnlyDatabase(); //ImSingleton.getInstance()?.dataBase;
    List<Map<String, dynamic>>? list = await database?.rawQuery("select * from im_group_user where groupId = ?", [groupId]);
    if (list != null && list.isNotEmpty) {
      List<ImGroupUser> result = list.map((map)=> _toImGroupUser(map)).toList();
      return Future.value(result);
    }
    return Future.value([]);
  }

  Future<ImGroupUser?> getByGroupIdAndUserId(int groupId, String userId) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    List<Map<String, dynamic>>? list = await database?.rawQuery("select * from im_group_user where groupId = ? and "
        "userId = ?", [groupId, userId]);
    if (list != null && list.isNotEmpty) {
      return _toImGroupUser(list[0]);
    }
    return null;
  }

  Map<String, Object?> _toInsertValueMap(int groupId, ImGroupUser groupUser) {
    Map<String, Object?> map = {};
    map['userId'] = groupUser.userId;
    map['groupId'] = groupId;
    map["status"]= groupUser.status.value;
    map['userName'] = groupUser.userName;
    map['isWaking'] = groupUser.isWaking ? 1 : 0;
    map['isShowName'] = groupUser.isShowName ? 1 : 0;
    map['isTop'] = groupUser.isTop ? 1 : 0;
    map['isDisturb'] = groupUser.isDisturb ? 1 : 0;
    map['remark'] = groupUser.remark;
    map['ext1'] = groupUser.ext1;
    map['ext2'] = groupUser.ext2;
    map['createTime'] = DateUtil.formatDate(groupUser.createTime);
    map['updateTime'] = DateUtil.formatDate(groupUser.updateTime);

    return map;
  }

  Map<String, Object?> _toUpdateValueMap(ImGroupUser groupUser) {
    Map<String, Object?> map = {};
    map["status"]= groupUser.status.value;
    map['userName'] = groupUser.userName;
    map['isWaking'] = groupUser.isWaking ? 1 : 0;
    map['isShowName'] = groupUser.isShowName ? 1 : 0;
    map['isTop'] = groupUser.isTop ? 1 : 0;
    map['isDisturb'] = groupUser.isDisturb ? 1 : 0;
    map['remark'] = groupUser.remark;
    map['ext1'] = groupUser.ext1;
    map['ext2'] = groupUser.ext2;
    map['updateTime'] = DateUtil.formatDate(groupUser.updateTime);

    return map;
  }

  ImGroupUser _toImGroupUser(Map<String, dynamic> map) {
    var imGroupUser = ImGroupUser(MapUtil.getString(map, "userId"));
    imGroupUser.id = MapUtil.getInt(map, "id");
    imGroupUser.groupId = MapUtil.getInt(map, "groupId");
    imGroupUser.userName = MapUtil.getStringOrNull(map, "userName");
    imGroupUser.remark = MapUtil.getStringOrNull(map, "remark");
    imGroupUser.isShowName = MapUtil.getBoolean(map, "isShowName");
    imGroupUser.isWaking = MapUtil.getBoolean(map, "isWaking");
    imGroupUser.isTop = MapUtil.getBoolean(map, "isTop");
    imGroupUser.isDisturb = MapUtil.getBoolean(map, "isDisturb");
    imGroupUser.status = ImGroupUserStatus.ofValue(MapUtil.getInt(map, "status"));
    imGroupUser.ext1 = MapUtil.getStringOrNull(map, "ext1");
    imGroupUser.ext2 = MapUtil.getStringOrNull(map, "ext2");
    imGroupUser.createTime = MapUtil.getDate(map, "createTime");
    imGroupUser.updateTime = MapUtil.getDate(map, "updateTime");
    return imGroupUser;
  }
}